TypeScriptで登録した関数をVim scriptを経由して動的に呼び出す
根本的にRemote Pluginと FuncRef の相性が悪い(TSでは全てnullになる)
例えば fzf#run には FuncRef を渡す必要がある
TS側では FuncRef を扱うことができないので、Vim scriptを経由して fzf#run を呼び出す
TSからVim scriptに渡す事ができるのは registerFunction で登録した関数名のみで、その関数も実行されるまで評価されないので function(func_name) で FuncRef を取得することができない
以下のコードで解決する、ポイントは function('s:handler_wrapper', [func_name]) と call call(func_name)
code:remote/runner.vim
function! fzf_preview#remote#runner#fzf_run(params) abort
call fzf#run({
\ 'source': source,
\ 'sink*': function('s:handler_wrapper', handler), \ 'options': options,
\ 'window': fzf_preview#window#float_or_normal_layout(),
\ })
endfunction
function! s:handler_wrapper(handler, lines) abort
call call(a:handler, a:lines)
endfunction
呼び出し側
code:fzf-runner.ts
type Parameter = {
source: Array<string>
handler: string
options: FzfOptions
}
export const fzfRunner = ({ source, handler, options }: Parameter) => {
pluginCall("fzf_preview#remote#runner#fzf_run", {
source,
handler,
options: fzfOptionsToString(options)
})
}
function('s:handler_wrapper', [handler]) で s:handler_wrapper(handler, lines) に handler: string を渡しながら fzf の実行結果として第2引数に lines を受け取る(高階関数的な感じ)
call call(a:handler, a:lines) でTSで registerFunction した関数に lines を渡して呼び出す
code:help call()
call({func}, {arglist} {dict}) *call()* *E699*
リスト|List|{arglist}の要素を引数として関数{func}を呼ぶ。
{func}は|Funcref|でも関数の名前でもよい。
a:firstlineとa:lastlineにはカレント行が代入される。
呼び出した関数の戻り値を返す。
{dict}は "dict" 属性つきの関数用で、これがローカル変数 "self"
に代入される。|Dictionary-function|を参照。
call call() なのは call() 関数を call コマンドで実行しているから
Vim scriptの関数を呼ぶ場合は a:lines を [a:lines] にしないといけないけど、TSで registerFunction した関数を呼ぶ場合は不要
おそらくTSの関数に渡すときに arglist を配列にwrapしているため
2つ以上引数を渡すときは call call(a:handler, [arg1, arg2]) してTS側で引数を展開する必要があるはず